﻿using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Collections.Generic;
using System.Threading;

namespace SBPweb.Messenger.Host.Services.WLM
{

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class ConnectionManager : WLMManagerBase, IConnectionManager
    {

        #region Private helpers

        private IConnectionManagerClient duplexClient;
        private bool processed = false;

        #endregion

        #region Property accessors

        public bool IsOnline
        {
            get
            {
                return Messenger.Connected;
            }
        }

        #endregion

        #region Methods

        #region Public functions

        public List<string> EnumeratePresenceStates()
        {
            List<string> ret = new List<string>(Enum.GetNames(typeof(PresenceStates)));

            ret.Remove("Offline");
            ret.Remove("Online");
            ret.Remove("Unknown");

            return ret;
        }

        public void SetPresenceState(string state)
        {
            SetPresenceState((PresenceStates)Enum.Parse(typeof(PresenceStates), state));
        }

        public void SetPresenceState(PresenceStates state)
        {
            Messenger.Nameserver.SetPresenceStatus(GetPresenceStatus(state));
        }

        public void Connect(string userName, string password)
        {
            duplexClient = OperationContext.Current.GetCallbackChannel<IConnectionManagerClient>();

            Messenger.Credentials.Account = userName;
            Messenger.Credentials.Password = password;
            Messenger.Connect();
        }

        public void Order(Message receivedMessage)
        {
            // Grab the client callback channel.
            duplexClient = OperationContext.Current.GetCallbackChannel<IConnectionManagerClient>();

            // Pretend that the service is processing and will call the client back in 5 seconds.
            using (Timer timer = new Timer(new TimerCallback(CallClient), receivedMessage.GetBody<string>(), 5000, 5000))
            {
                Thread.Sleep(11000);

            }
        }

        #endregion

        #region Private helper functions
        
        private static MSNPSharp.PresenceStatus GetPresenceStatus(PresenceStates state)
        {
            switch (state)
            {
                case PresenceStates.Away:
                    return MSNPSharp.PresenceStatus.Away;
                case PresenceStates.BeRightBack:
                    return MSNPSharp.PresenceStatus.BRB;
                case PresenceStates.Busy:
                    return MSNPSharp.PresenceStatus.Busy;
                case PresenceStates.Hidden:
                    return MSNPSharp.PresenceStatus.Hidden;
                case PresenceStates.Idle:
                    return MSNPSharp.PresenceStatus.Idle;
                case PresenceStates.Lunch:
                    return MSNPSharp.PresenceStatus.Lunch;
                case PresenceStates.Offline:
                    return MSNPSharp.PresenceStatus.Offline;
                case PresenceStates.Online:
                    return MSNPSharp.PresenceStatus.Online;
                case PresenceStates.InPhoneCall:
                    return MSNPSharp.PresenceStatus.Phone;
                default:
                case PresenceStates.Unknown:
                    return MSNPSharp.PresenceStatus.Unknown;
            }
        }

        private static PresenceStates GetPresenceState(MSNPSharp.PresenceStatus status)
        {
            switch (status)
            {
                case MSNPSharp.PresenceStatus.Away:
                    return PresenceStates.Away;
                case MSNPSharp.PresenceStatus.BRB:
                    return PresenceStates.BeRightBack;
                case MSNPSharp.PresenceStatus.Busy:
                    return PresenceStates.Busy;
                case MSNPSharp.PresenceStatus.Hidden:
                    return PresenceStates.Hidden;
                case MSNPSharp.PresenceStatus.Idle:
                    return PresenceStates.Idle;
                case MSNPSharp.PresenceStatus.Lunch:
                    return PresenceStates.Lunch;
                case MSNPSharp.PresenceStatus.Offline:
                    return PresenceStates.Offline;
                case MSNPSharp.PresenceStatus.Online:
                    return PresenceStates.Online;
                case MSNPSharp.PresenceStatus.Phone:
                    return PresenceStates.InPhoneCall;
                default:
                case MSNPSharp.PresenceStatus.Unknown:
                    return PresenceStates.Unknown;
            }
        }


        private void CallClient(object order)
        {
            string text;

            // Process order
            if (processed)
            {
                text = (string)order + " order complete";
            }
            else
            {
                text = "Processing " + (string)order + " order";
                processed = true;
            }

            // Construct the message to return to the client.
            Message returnMessage = Message.CreateMessage(MessageVersion.Soap11, "SBPweb.Messenger.WLM/IConnectionManager/Recieve", text);

            // Call the client back.
            duplexClient.Receive(returnMessage);
        }

        #endregion

        #endregion

    }

}